package yxy.game.pm2.module.playerCommand;

import yxy.apple.logger.Logger;
import yxy.cherry.battle.Battle;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.skillpoint;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.message.PlayerMessage;
import yxy.game.pm2.module.CurrencyHandle;

import java.sql.ResultSet;
import java.util.*;

/**
 * @author wrs
 * @since 2022-08-04
 * */
public class PlayerCommandHandler {

    /**
     * 统御信息封装
     * @param playerCommandModule
     * @param response
     * @return
     */
    public Result packCommandInfo(PlayerCommandModule playerCommandModule, PlayerMessage.PlayerCommandInfoResponse.Builder response) {

        int[] propertyLevel = playerCommandModule.getPropertyLevel(); //攻防血属性等级
        if (propertyLevel.length == 0){
            return Result.DataError;
        }

        PlayerMessage.Property.Builder propertyBuilder = PlayerMessage.Property.newBuilder();

        response.setSurplusPoint(playerCommandModule.getPoint()); //玩家点数，初始值为玩家等级

        propertyBuilder.setAttack(propertyLevel[0]); //攻击等级
        propertyBuilder.setDefense(propertyLevel[1]);//防御等级
        propertyBuilder.setLife(propertyLevel[2]);//生命等级
        response.setProperty(propertyBuilder);

        return Result.Success;
    }

    /**
     * 重置攻防血属性，返还点数
     * @param playerCommandModule
     * @param playerCode
     */
    public Result resetProperty(PlayerCommandModule playerCommandModule, String playerCode) throws CurrencyNotEnoughException {
        //TODO 点数都为0，直接返回
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < playerCommandModule.getPropertyLevel().length; i++) {
            int propertyLevel = playerCommandModule.getPropertyLevel(i);
            if (propertyLevel == 0){
                list.add(propertyLevel);
            }
        }
        if (list.size() == 3){
            return Result.Success;
        }

        //todo 获取已使用的所有点数,重置攻防血属性加成
        int totalPoint = 0;
        for (int i = 0; i < playerCommandModule.getPropertyLevel().length; i++) {
            int point = playerCommandModule.getPropertyLevel()[i];
            totalPoint += point;
            playerCommandModule.getPropertyLevel()[i] = 0;
        }
        //todo 消耗元宝
        Currency costCurrency = getCostCurrency(playerCommandModule);
        Battle.battleLogger(1,"主公点数重置消耗，currencyType_"+costCurrency.getType().getNumber()+" currencyId_"+costCurrency.getDataId()+" currencyNum_"+costCurrency.getNumber());

        boolean isEnough = new CurrencyHandle().costCheck(playerCode, costCurrency);
        if (isEnough){
            new CurrencyHandle().cost(playerCode, CCReason.主公点数重置,costCurrency);
        }else {
            return Result.CostFail;
        }

        //todo 返还点数
        playerCommandModule.setPoint(playerCommandModule.getPoint() + totalPoint);

        //todo 重置次数加1
        playerCommandModule.setResetTimes(playerCommandModule.getResetTimes() + 1);

        playerCommandModule.set(playerCode);
        return Result.Success;
    }

    /**
     * 消耗点数提升 攻防血属性
     * @param propertyLevelList
     * @param playerCommandModule
     * @param playerCode
     */
    public Result costPointToUpgrade(List<Integer> propertyLevelList, PlayerCommandModule playerCommandModule, String playerCode) {

        //todo 校验点数和与等级是否相等
        int sum = 0;
        for (Integer val : propertyLevelList) {
            sum += val;
        }
        PlayerBean playerBean = PlayerBean.get(playerCode);
        if (sum > playerBean.getLevel()){
            return Result.DataError;
        }

        //todo 修改对应属性的点数
        for (int i = 0; i < propertyLevelList.size(); i++) {
            if (propertyLevelList.get(i) != 0){
                //属性等级修改
                int oldLevel = playerCommandModule.getPropertyLevel(i);
                playerCommandModule.setPropertyLevel(i,propertyLevelList.get(i));
                playerCommandModule.setPoint(playerCommandModule.getPoint() - (propertyLevelList.get(i) - oldLevel));
                playerCommandModule.set(playerCode);
            }
        }
        return Result.Success;
    }

    /**
     * 重置信息封装
     * @param playerCommandModule
     * @param response
     * @return
     */
    public Result packResetInfo(PlayerCommandModule playerCommandModule, PlayerMessage.PlayerPointResetResponse.Builder response) {

        int[] propertyLevel = playerCommandModule.getPropertyLevel(); //攻防血属性等级
        if (propertyLevel.length == 0){
            return Result.DataError;
        }

        PlayerMessage.Property.Builder propertyBuilder = PlayerMessage.Property.newBuilder();

        response.setSurplusPoint(playerCommandModule.getPoint()); //玩家点数，初始值为玩家等级

        propertyBuilder.setAttack(propertyLevel[0]); //攻击等级
        propertyBuilder.setDefense(propertyLevel[1]);//防御等级
        propertyBuilder.setLife(propertyLevel[2]);//生命等级
        response.setProperty(propertyBuilder);

        Currency costCurrency = getCostCurrency(playerCommandModule);
        response.setRewards(new CurrencyHandle().packItem(costCurrency));

        return Result.Success;
    }

    /**
     * 封装点数消耗后信息
     * @param playerCommandModule
     * @param response
     * @return
     */
    public Result packPointCostInfo(PlayerCommandModule playerCommandModule, PlayerMessage.PlayerPointCostResponse.Builder response) {

        response.setSurplusPoint(playerCommandModule.getPoint()); //剩余点数

        PlayerMessage.Property.Builder propertyBuilder = PlayerMessage.Property.newBuilder();
        propertyBuilder.setAttack(playerCommandModule.getPropertyLevel()[0]); //攻击
        propertyBuilder.setDefense(playerCommandModule.getPropertyLevel()[1]); //防御
        propertyBuilder.setLife(playerCommandModule.getPropertyLevel()[2]); //生命

        response.setProperty(propertyBuilder);

        return Result.Success;
    }

    /**
     * 检查最高级不能超过最低级 5%
     * @param propertyLevelList
     * @param playerCommandModule
     * @return
     */
    public Result checkProperty(List<Integer> propertyLevelList,PlayerCommandModule playerCommandModule) {
        //边界值判断
        for (Integer val : propertyLevelList) {
            if ((val > 0 && Integer.MAX_VALUE / 10 < val) || (val < 0 && Integer.MIN_VALUE / 10 > val)){
                return Result.DataError;
            }
        }

        ArrayList<Integer> resultLevelList = new ArrayList<>(); //加点后的属性等级
        for (int i = 0; i < propertyLevelList.size(); i++) {
            if (propertyLevelList.get(i) == playerCommandModule.getPropertyLevel(i)){
                resultLevelList.add(playerCommandModule.getPropertyLevel(i));
                continue;
            }
            resultLevelList.add(propertyLevelList.get(i));
        }

        //todo 获取最大值和最小值下标
        Integer max = Collections.max(resultLevelList);
        int indexOfMax = resultLevelList.indexOf(max);

        Integer min = Collections.min(resultLevelList);

        //根据表获取增幅（万分比）,默认选取攻击增幅
        int scala = 0;
        Map<String, skillpoint> allData = DataCenter.getAllData(skillpoint.class);
        for (skillpoint skillpoint : allData.values()) {
            if (indexOfMax + 1 == skillpoint.getField() && max >= skillpoint.getMinlevel() && max < skillpoint.getMaxlevel()){
                scala = skillpoint.getAttackscale();
                break;
            }
        }

        double resultScala = (double)(max - min) * scala / 10000;
        if (resultScala > 0.05){
            return Result.PropertyMoreThanLimit; //单项属性加成超过最低项 5%
        }else {
            return Result.Success;
        }

    }

    /**
     * 获取重置需要消耗的代币
     * @param playerCommandModule
     * @return
     */
    public Currency getCostCurrency(PlayerCommandModule playerCommandModule) {
        Map<String, skillpoint> allData = DataCenter.getAllData(skillpoint.class);

        int costType = 0;
        int costId = 0;
        int costNum = 0;

        int resetTimes = playerCommandModule.getResetTimes(); //重置次数,初始值为0
        for (skillpoint skillpoint : allData.values()) {
            if (skillpoint != null){
                costType = skillpoint.getCosttype();
                costId = skillpoint.getCostid();
                costNum = skillpoint.getCostnum();
                break;
            }
        }

        return Currency.create(costType, costId, costNum * (resetTimes + 1));
    }
}
